package me.magicall.db.dao2;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import me.magicall.db.dao.CommonDao;
import me.magicall.db.dao2.sql.SqlBuilder;
import me.magicall.db.dao2.sql.SqlBuilder.ParamedSqlAndParams;
import me.magicall.db.util.OptionOnExist;

public abstract class ToSqlDao<T> extends AbsDaoImpl<T> {

	protected ToSqlDao() {
		super();
	}

	protected ToSqlDao(final CommonDao<T> commonDao) {
		super(commonDao);
	}

	@Override
	public List<T> list(final Query<T> query) {
		final ParamedSqlAndParams paramedSqlAndParams = listSqlBuilder().buildSql(query);
		final List<Map<String, Object>> list = readFromDB(paramedSqlAndParams.paramedSql, paramedSqlAndParams.params);
		final List<T> rt = new ArrayList<T>(list.size());
		for (final Map<String, Object> row : list) {
			rt.add(rowToModel(row));
		}
		return rt;
	}

	@Override
	public int count(final Query<T> query) {
		final ParamedSqlAndParams paramedSqlAndParams = countSqlBuilder().buildSql(query);
		return queryForInt(paramedSqlAndParams.paramedSql, paramedSqlAndParams.params);
	}

	@Override
	public int del(final Query<T> query) {
		final ParamedSqlAndParams paramedSqlAndParams = countSqlBuilder().buildSql(query);
		return writeToDB(paramedSqlAndParams.paramedSql, paramedSqlAndParams.params);
	}

	protected abstract T rowToModel(Map<String, Object> row);

	protected abstract List<Map<String, Object>> readFromDB(String sql, Map<String, ? extends Object> params);

	protected abstract int queryForInt(String sql, Map<String, ? extends Object> params);

	protected abstract int writeToDB(String sql, Map<String, ? extends Object> params);

	protected abstract SqlBuilder listSqlBuilder();

	protected abstract SqlBuilder countSqlBuilder();

	protected abstract SqlBuilder updateSqlBuilder();

	protected abstract SqlBuilder delSqlBuilder();

	protected abstract SqlBuilder insertSqlBuilder(OptionOnExist optionOnExist);
}
